/**
 * @file reader.c
 * Betriebssysteme Shared Memory Reader.
 *
 * Beispiel 2
 *
 * @author Markus Scharitzer 1410258040 <markus.scharitzer@technikum-wien.at>
 * @author Helene Wiesinger 1410258004 <helene.wiesinger@technikum-wien.at>
 * @author Siegfried Becher 141025035 <siegfried.becher@technikum-wien.at>
 * @date 2015/06/04
 *
 * @version 1.0
 *
 * Reads from a shared memory.
 * 
 */

#include "shmem.h"


int main(int argc, char *argv[])
{
  int size = 0;
  int shared_memory_key = -1;
  int sem_r = -1;
  int sem_w = -1;
  int cnt = -1;
  int buf = -1;
  int *shared_memory = NULL;

  errno = 0;


  /* check command line arguments */
  if ((size = check_arguments(argc, argv))==ERROR)
    {
      print_usage();
      return ERROR;
    }
  /* get both semaphores */
  if((shared_memory_key = get_shmem(SHMEMKEY, size)) == -1)
    {
      clean_up(sem_r, &shared_memory, shared_memory_key, ERROR);
      return ERROR;
    }
  attach_shmem(shared_memory_key, &shared_memory, SEMKEY_R);
  if(shared_memory == NULL)
    {
      clean_up(sem_r, &shared_memory, shared_memory_key, ERROR);
      return ERROR;
    }
  /* initialize shared memory */
  if((sem_r= get_semid(SEMKEY_R, 0)) == ERROR)
    {
      clean_up(sem_r, &shared_memory, shared_memory_key, ERROR);
      return ERROR;
    }
  /* attach memory to process */
  if((sem_w= get_semid(SEMKEY_W, size))==ERROR)
    {
      clean_up(sem_r, &shared_memory, shared_memory_key, ERROR);
      return ERROR;
    }

  /* start the reader */
  do
    {
      if(P(sem_r)==-1)
	{
	  if(errno == EINTR)
            {
	      /*EINTR sagt uns, dass ein Interrupt vorliegt. */
	      errno = 0;
	      continue;
            }
	  else
            {
	      clean_up(sem_r, &shared_memory, shared_memory_key, ERROR);
	      fprintf(stderr, "Error bei P, reader. %s", strerror(errno));
	      return ERROR;
            }
        }
      cnt++;
      cnt = cnt%size;
      buf = (*(shared_memory+cnt));

      if(V(sem_w)==-1)
	{
	  if(errno == EINTR)
            {
	      /*EINTR sagt uns, dass ein Interrupt vorliegt. */
	      errno = 0;
	      continue;
            }
	  else
            {
	      clean_up(sem_r, &shared_memory, shared_memory_key, ERROR);
	      fprintf(stderr, "Error bei V, reader. %s", strerror(errno));
	      return ERROR;
            }
        }
      if(buf!=EOF)
        {
	  /* Do ouput and check for Output error */
	  if (fputc(buf, stdout) == EOF) {
	    fprintf(stderr, "Fehler fputc");
	    clean_up(sem_r, &shared_memory, shared_memory_key, ERROR);
	    return ERROR;

	  }
        }
    }while(buf!=EOF);

  errno = 0;
  if(fflush(stdout)!=0)
    {
      fprintf(stderr, "fflush failed");
      if(errno != 0)
        {
	  fprintf(stderr, "%s", strerror(errno));
	  return ERROR;
        }
    }

  detach_shmem(shared_memory_key,SEMKEY_R);
  clean_up(sem_r, &shared_memory, shared_memory_key, SEMKEY_R);
  return 0;

}
